/**
 * 
 */
package loansManagement;

import hibernateUtils.HibernateUtil;

import java.io.Serializable;
import java.util.Calendar;
import java.util.GregorianCalendar;

import javax.persistence.AssociationOverride;
import javax.persistence.AttributeOverride;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Transient;

import org.hibernate.Session;

import exceptions.BadParametersException;
import exceptions.ChildLoanException;
import exceptions.ReservationMediaException;

import mediasManagement.Exemplary;
import mediasManagement.Media;
import rappelEmail.SendEmail;
import subscribersManagement.Subscriber;

/** 
 * @author virgil
 */
@Entity
@AssociationOverride(name = "pk.subscriber",
			joinColumns=@JoinColumn(name="SUBSCRIBER_ID"))
@AttributeOverride(name = "pk.media",
			column=@Column(name="MEDIA_ID"))
public class Reservation {

	
	
	/**
	 * @uml.property  name="beginAvalaibilityDate"
	 */
	private Calendar beginAvalaibilityDate;

	public Reservation(){
		this.pk=new ReservationId();
	}
	public Reservation(Media media, Subscriber lender) throws BadParametersException, ReservationMediaException, ChildLoanException {
		// TODO Auto-generated constructor stub
		if ((media == null) || (lender == null))
			throw new BadParametersException();
		
		this.pk = new ReservationId();
		
		setSubscriber(lender);
		setMedia(media);
		//if a exemplary is available, we give interval date to take it
		Exemplary m=media.availableExemplary();
		if(m!=null){
			beginAvalaibilityDate=new GregorianCalendar();
			endAvailibilityDate=new GregorianCalendar();
			endAvailibilityDate.add(Calendar.DATE, 14);
			exemplaryId=m.getExemplaryId();
			m.setReserved(true);
			SendEmail.sendReservationMail(this);
			Session session= HibernateUtil.openSession();
	        session.merge(m);
			
		}
		//update media reservations
		media.reserve(this);
		
		//upddate subscriber reservations
		lender.reserve(this);
	}

	/**
	 * Getter of the property <tt>beginAvalaibilityDate</tt>
	 * @return  Returns the beginAvalaibilityDate.
	 * @uml.property  name="beginAvalaibilityDate"
	 */
	public Calendar getBeginAvalaibilityDate() {
		return beginAvalaibilityDate;
	}

	/**
	 * Setter of the property <tt>beginAvalaibilityDate</tt>
	 * @param beginAvalaibilityDate  The beginAvalaibilityDate to set.
	 * @uml.property  name="beginAvalaibilityDate"
	 */
	public void setBeginAvalaibilityDate(Calendar beginAvalaibilityDate) {
		this.beginAvalaibilityDate = beginAvalaibilityDate;
	}

	/**
	 * @uml.property  name="endAvailibilityDate"
	 */
	private Calendar endAvailibilityDate;

	/**
	 * Getter of the property <tt>endAvailibilityDate</tt>
	 * @return  Returns the endAvailibilityDate.
	 * @uml.property  name="endAvailibilityDate"
	 */
	public Calendar getEndAvailibilityDate() {
		return endAvailibilityDate;
	}

	/**
	 * Setter of the property <tt>endAvailibilityDate</tt>
	 * @param endAvailibilityDate  The endAvailibilityDate to set.
	 * @uml.property  name="endAvailibilityDate"
	 */
	public void setEndAvailibilityDate(Calendar endAvailibilityDate) {
		this.endAvailibilityDate = endAvailibilityDate;
	}

	private String exemplaryId;

	/**
	 * Getter of the property <tt>media</tt>
	 * @return  Returns the media.
	 * @uml.property  name="media"
	 */
	@Transient
	public Media getMedia() {
		return getPk().getMedia();
	
	}

	/**
	 * Setter of the property <tt>media</tt>
	 * @param media  The media to set.
	 * @uml.property  name="media"
	 */
	public void setMedia(Media media) {
		getPk().setMedia(media);
	}

	/**
	 * @uml.property  name="subscriber"
	 * @uml.associationEnd  inverse="reservations:subscribersManagement.Subscriber"
	 */
	

	/**
	 * Getter of the property <tt>subscriber</tt>
	 * @return  Returns the subscriber.
	 * @uml.property  name="subscriber"
	 */
	@Transient
	public Subscriber getSubscriber() {
		return getPk().getSubscriber();
	}

	/**
	 * Setter of the property <tt>subscriber</tt>
	 * @param subscriber  The subscriber to set.
	 * @uml.property  name="subscriber"
	 */
	public void setSubscriber(Subscriber subscriber) {
		getPk().setSubscriber(subscriber);
	}
	
	public String toString(){
		 
		return getSubscriber().toString()+" reserve  "+"\""+getMedia().getTitle()+"\"";
		 
	 }

	/**
	 * @uml.property  name="pk"
	 * @uml.associationEnd  inverse="reservation:mediasManagement.ReservationId"
	 */
	@EmbeddedId
	private ReservationId pk;

	/**
	 * Getter of the property <tt>pk</tt>
	 * @return  Returns the pk.
	 * @uml.property  name="pk"
	 */
	public ReservationId getPk() {
		return pk;
	}

	/**
	 * Setter of the property <tt>pk</tt>
	 * @param pk  The pk to set.
	 * @uml.property  name="pk"
	 */
	public void setPk(ReservationId pk) {
		this.pk = pk;
	}

	
	
	public boolean equals(Object o) {
		if (this == o)
			return true;
		if (o == null || getClass() != o.getClass())
			return false;
	
		Reservation that = (Reservation) o;
	
		if (getPk() != null ? !getPk().equals(that.getPk())
				: that.getPk() != null)
			return false;
	
		return true;
	}
	
	public int hashCode() {
		return (getPk() != null ? getPk().hashCode() : 0);
	}
	/**
	 * @return the exemplaryId
	 */
	public String getExemplaryId() {
		return exemplaryId;
	}
	/**
	 * @param exemplaryId the exemplaryId to set
	 */
	public void setExemplaryId(String exemplaryId) {
		this.exemplaryId = exemplaryId;
	}

	

}
